package framework.spring;

import framework.annotation.XReference;
import framework.annotation.XService;
import framework.common.XConfig;
import framework.config.XServiceConfig;
import framework.provier.ServiceProvider;
import framework.proxy.ClientProxy;
import framework.transport.cluster.Cluster;
import framework.transport.cluster.FailFastCluster;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;

@Component
public class PublishService implements BeanPostProcessor, ApplicationContextAware {


    @Autowired
    private ServiceProvider serviceProvider;

//    @Autowired
//    private Cluster cluster;

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext context) {
        applicationContext = context;
    }

    @Autowired
    private XConfig xConfig;
    private PublishService() {
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        XService annotation = bean.getClass().getAnnotation(XService.class);
        if (annotation != null) {
            XServiceConfig config = new XServiceConfig(annotation.version(), annotation.group(), bean);
            serviceProvider.publishService(config);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        if (xConfig.getConsumer() == null) {
            return bean;
        }
        Class<?> targetClass = bean.getClass();
        Field[] declaredFields = targetClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            XReference rpcReference = declaredField.getAnnotation(XReference.class);
            if (rpcReference != null) {
                XServiceConfig rpcServiceConfig = XServiceConfig.builder()
                        .group(rpcReference.group())
                        .version(rpcReference.version()).build();
                Cluster cluster = applicationContext.getBean(Cluster.class);
                ClientProxy clientProxy = new ClientProxy(rpcServiceConfig, cluster);
                Object proxy = clientProxy.getProxy(declaredField.getType());
                declaredField.setAccessible(true);
                try {
                    declaredField.set(bean, proxy);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

        }
        return bean;
    }
}
